package com.dylan.channel.v6.channel;

import com.dylan.channel.v6.EventLoop;
import com.dylan.channel.v6.NioEventLoop;

import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;

public abstract class AbstractNioChannel extends AbstractChannel {

    private final SelectableChannel ch;
    volatile SelectionKey selectionKey;

    protected AbstractNioChannel(Channel parent, SelectableChannel ch) {
        super(parent);
        this.ch = ch;
    }

    protected SelectableChannel javaChannel() {
        return this.ch;
    }

    /**
     * Read from underlying {@link SelectableChannel}
     */
    abstract void read();


    @Override
    public NioEventLoop eventLoop() {
        return (NioEventLoop) super.eventLoop();
    }

    protected void doRegister() {
        boolean selected = false;

        while (true) {
            try {
                this.selectionKey = this.javaChannel().register(this.eventLoop().getSelect(), 0, this);
                return;
            } catch (Exception e) {
                if (selected) {
                    throw new RuntimeException(e.getMessage());
                }
                //this.eventLoop().selectNow();
                selected = true;
            }
        }
    }


    protected abstract class AbstractNioUnsafe extends AbstractUnsafe implements NioUnsafe {

    }

    public interface NioUnsafe extends Channel.Unsafe {
        SelectableChannel ch();

        void read();

    }
}
